import * as THREE from 'three';
import * as utils from '../utils'

// FF 91 Constants
class FF91Const {
    Accel = 5; // m/s^2
    Decel = -10; // m/s^2
    MaxVel = (70 * 1610) / 3600; // 70m/h ~= 31.3m/s
    MaxTurn = Math.PI * 0.20; // Max angle of wheel turn
    // Dimensions 尺寸
    Length = 5.250; // Car length
    Width = 2.283; // Car width
    WheelTrack = 1.72; // Wheel track 车辙宽度
    WheelBase = 3.200; // Wheel base  轴距
    WheelDiam = 0.780; // Wheel diameter 轮胎直径
    WheelCirc = this.WheelDiam * Math.PI; // Wheel circumference 轮胎周长
}

export const FF91 =  new FF91Const()

export class CarProps{
    constructor(){
        console.log('车辆参数类')
        this.time = new utils.Time(); // 计时器
        this.velocity = new THREE.Vector2(); // 速度
        this.speed = 0;
        this.accel = 0;
        this.pos = new THREE.Vector2();
        this.joyVec = new THREE.Vector2();
        // Momentim
        this.longitMomentum = 0;
        this.lateralMomentum = 0;
        this.wAngleInner = 0;
        this.wAngleOuter = 0;
        this.wAngleTarg = 0; // 轮胎转弯角度
        this.keys = new Array();
        this.braking = 0.0;
        this.omega = 0;
        this.theta = -Math.PI / 2;
    }
    onKeyDown (evt) {
        // Add key to list if they don't exist yet
        if (this.keys.indexOf(evt.keyCode) === -1) {
            this.keys.push(evt.keyCode);
        }
    };
    onKeyUp (evt) {
        //Otherwise, remove from keys list
        this.keys.splice(this.keys.indexOf(evt.keyCode), 1);
    };
    readKeyboardInput () {
        for (var i = 0; i < this.keys.length; i++) {
            switch (this.keys[i]) {
                case 38:// Up
                    this.accel += FF91.Accel;
                    // Simulate wind resistance as we reach top speed
                    this.accel *= utils.normalizeQuadIn(this.speed, FF91.MaxVel, FF91.MaxVel - 10);
                    break;
                case 40:// Down
                    this.accel += FF91.Decel;
                    this.braking = 1;
                    break;
                case 37:// Left
                    this.wAngleTarg += FF91.MaxTurn;
                    break;
                case 39:// Right
                    this.wAngleTarg -= FF91.MaxTurn;
                    break;
            }
        }
    };
   
    /////////////////////////////// UPDATE ///////////////////////////////
    update (_time) {
        // Update time, skips according to FPS
        if (this.time.update(_time) === false) {
            return false;
        }
        this.accel = 0;
        this.braking = 0;
        this.wAngleTarg = 0;
        if (this.keys.length > 0) {
            this.readKeyboardInput();
        }
        
        ///////////////// PHYSICS, YO! 物理引擎/////////////////
        this.accel *= this.time.delta;
        this.speed += this.accel;
        if (this.speed < 0) {
            this.speed = 0;
            this.accel = 0;
        }
        this.frameDist = this.speed * this.time.delta;
        // Limit turn angle as speed increases 根据速度增量限制转弯角度
        this.wAngleTarg *= utils.normalizeQuadIn(this.speed, FF91.MaxVel + 10.0, 3.0); // 轮胎转弯角度
        this.wAngleInner = utils.zTween(this.wAngleInner, this.wAngleTarg, this.time.delta * 2);
        this.wAngleSign = this.wAngleInner > 0.001 ? 1 : this.wAngleInner < -0.001 ? -1 : 0;// 轮胎转弯标识
        // Theta is based on speed, wheelbase & wheel angle
        this.omega = this.wAngleInner * this.speed / FF91.WheelBase;
        this.theta += this.omega * this.time.delta;
        // Calc this frame's XY velocity
        this.velocity.set(Math.cos(this.theta) * this.frameDist, -Math.sin(this.theta) * this.frameDist);
        // Add velocity to total position
        this.pos.add(this.velocity);
        // Fake some momentum
        this.longitMomentum = utils.zTween(this.longitMomentum, this.accel / this.time.delta, this.time.delta * 6);
        this.lateralMomentum = this.omega * this.speed;
        if (this.wAngleSign) {
            // Calculate 4 wheel turning radius if angle
            this.radFrontIn = FF91.WheelBase / Math.sin(this.wAngleInner);
            this.radBackIn = FF91.WheelBase / Math.tan(this.wAngleInner);
            this.radBackOut = this.radBackIn + (FF91.WheelTrack * this.wAngleSign);
            this.wAngleOuter = Math.atan(FF91.WheelBase / this.radBackOut);
            this.radFrontOut = FF91.WheelBase / Math.sin(this.wAngleOuter);
        }
        else {
            // Otherwise, just assign a very large radius.
            this.radFrontOut = 100;
            this.radBackOut = 100;
            this.radBackIn = 100;
            this.radFrontIn = 100;
            this.wAngleOuter = 0;
        }
        return true;
    };
}